Categories
Vue 3

Form Validation in a Vue 3 App with Vee-Validate 4 — Validate Nested Objects

Spread the love

Form validation is an important part of any app.

In this article, we’ll look at how to use Vee-Validate 4 in our Vue 3 app for form validation.

Call Set Form Validation Methods from Form’s ref

We can access the setFieldError and setErrors methods from the Form component’s ref.

For example, we can write:

<template>
  <Form @submit="onSubmit" ref="myForm">
    <Field name="email" as="input" />
    <ErrorMessage name="email" />
    <br />

    <Field name="password" as="input" />
    <ErrorMessage name="password" />
    <br />

    <input type="submit" />
  </Form>
</template>

<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {
    const schema = yup.object().shape({
      email: yup.string().required().email(),
      name: yup.string().required(),
      password: yup.string().required().min(8),
    });

    return {
      schema,
    };
  },
  methods: {
    onSubmit(values) {
      this.$refs.myForm.setFieldError("email", "this email is already taken");
      this.$refs.myForm.setErrors({
        email: "this field is already taken",
        password: "someone already has this password",
      });
    },
  },
};
</script>

We call setFieldError and setErrors from the form’s ref.

Validating Nested Objects

We can validate nested form objects with the Field component.

For example, we can write:

<template>
  <Form @submit="onSubmit" :validation-schema="schema">
    <Field name="links.twitter" type="url" />
    <ErrorMessage name="links.twitter" />
    <br />

    <Field name="links.github" type="url" />
    <ErrorMessage name="links.github" />
    <br />

    <button>Submit</button>
  </Form>
</template>

<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {
    const schema = yup.object().shape({
      links: yup.object().shape({
        twitter: yup.string().url(),
        github: yup.string().url(),
      }),
    });
    return {
      schema,
    };
  },
  methods: {
    onSubmit(values) {
      alert(JSON.stringify(values, null, 2));
    },
  },
};
</script>

We set the name attribute to the path to the field we want to validate in the Field and ErrorMessage components.

In the schema object, we do the same thing.

We call yup.object().shape() and add the links property inside the object we pass in as the argument.

Validating Nested Arrays

We can also use Vee-Validate 4 to validate nested arrays.

For instance, we can write:

<template>
  <Form @submit="onSubmit" :validation-schema="schema">
    <Field name="links[0]" type="url" />
    <ErrorMessage name="links[0]" />
    <br />

    <Field name="links[1]" type="url" />
    <ErrorMessage name="links[1]" />
    <br />

    <button>Submit</button>
  </Form>
</template>

<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
    ErrorMessage,
  },
  data() {
    const schema = yup.object().shape({
      links: yup.array().of(yup.string().url()),
    });
    return {
      schema,
    };
  },
  methods: {
    onSubmit(values) {
      alert(JSON.stringify(values, null, 2));
    },
  },
};
</script>

to add the array validation.

We can check if an array of strings is a URL by writing:

yup.array().of(yup.string().url())

Composition API

We can add validation to our Vue 3 components if we use the composition API.

To do this, we write:

<template>
  <Form @submit="onSubmit" v-slot="{ errors }" :validation-schema="schema">
    <Field name="user.name" as="input" />
    <span id="nameErr">{{ errors["user.name"] }}</span>
    <br />

    <Field name="user.addresses[0]" as="input" id="address" />
    <span id="addrErr">{{ errors["user.addresses[0]"] }}</span>
    <br />

    <button id="submit">Submit</button>
  </Form>
</template>

<script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
  },
  setup() {
    return {
      schema: yup.object({
        user: yup.object({
          name: yup.string().required(),
          addresses: yup.array().of(yup.string().required()),
        }),
      }),
      onSubmit(values) {
        console.log(values);
      },
    };
  },
};
</script>

The setUp method returns the schema reactive property and the onSubmit method.

Conclusion

We can validate forms with the composition API and validate objects and nested arrays.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *